<template>
	<el-main class="sw_agent_main" :style="{ marginLeft: isExpand ? '8px' : '0' }">
		<div class="agent_main_header">
			<div class="btn" v-if="isNewChat">
				<el-button type="text" icon="el-icon-refresh-left"></el-button>
				<el-popover placement="bottom-end" title="新对话设置" width="400" popper-class="agent_popover_class">
					<el-button slot="reference" type="text" icon="el-icon-setting"></el-button>
					<chat-setting size="small" v-model="settingData" disabled />
				</el-popover>
			</div>
			<div class="box" v-if="!isExpand">
				<el-button type="text" icon="el-icon-s-unfold" @click="handleChatAside"></el-button>
				<i class="icon">{{ siteData.icon }}</i>
				<h2>{{ siteData.title }}</h2>
				<el-divider direction="vertical"></el-divider>
				<el-button type="text" icon="el-icon-edit-outline" :disabled="!isNewChat" @click="handleAddedChat"></el-button>
			</div>
		</div>
		<el-scrollbar>
			<el-card class="agent_chat_setting">
				<template slot="header">
					<span>新对话设置</span>
					<el-button type="text" v-if="isNewChat && !isEditForm" @click="handleEditSetting()">编辑</el-button>
				</template>
				<chat-setting ref="form" size="medium" v-if="isEditForm" v-model="settingData">
					<el-button type="primary" @click="handleSaveSetting()">开始对话</el-button>
				</chat-setting>
			</el-card>
			<div class="agent_chat_content">
				<chat-item v-for="(item, index) in contents" :key="index" :data="item" />
			</div>
		</el-scrollbar>
		<div class="agent_chat_bottom">
			<el-input v-bind="inputConfig" v-model="chatInput" :disabled="!isCanChat" @keyup.enter.native="handleStartChat()" />
			<el-button type="primary" @click="handleStartChat()" :disabled="!isCanChat || !chatInput"></el-button>
		</div>
	</el-main>
</template>

<script>
import lodash from 'lodash';
import { SSE } from 'sse.js';
import chatItem from './item';
import { mapGetters } from 'vuex';
import chatSetting from '@/views/setting';
import handleMixins from '@/mixins/handle';
import { parseMarkdown } from '@/utils/function';
import { getChatMessage, runWorkflows } from '@/api/common';
export default {
	mixins: [handleMixins],
	components: { chatSetting, chatItem },
	data() {
		return {
			sseInstance: null,
			isEditForm: true,
			settingData: {},
			isEnded: true,
			chatInput: '',
			contents: [],
			inputConfig: {
				ref: 'chatRef',
				size: 'medium',
				placeholder: 'Talk to Bot'
			}
		};
	},
	computed: {
		...mapGetters(['siteData']),
		isCanChat() {
			return !this.isEditForm && !lodash.isEmpty(this.settingData);
		}
	},
	mounted() {
		this.getChatMessage();
	},
	methods: {
		//获取聊天记录
		async getChatMessage() {
			let params = { conversation_id: '', limit: 20 };
			let result = await getChatMessage(params);
			if (result.status === 200) {
				this.contents = result.data.data || [];
			}
		},

		handleSaveSetting() {
			this.$refs['form'].validateSetting((valid) => {
				if (!valid) return false;
				this.isEditForm = false;
				this.isNewChat = true;
				this.$nextTick(() => {
					this.$refs['chatRef'].focus();
				});
			});
		},

		handleEditSetting() {
			if (!this.isEditForm) {
				this.isEditForm = true;
				this.isNewChat = true;
			} else {
				this.handleSaveSetting();
			}
		},

		formatSubmitParams() {
			let params = { user: 'wjy', files: [] };
			params['inputs'] = { ...this.settingData };
			params['response_mode'] = 'streaming';
			params['query'] = this.chatInput;
			return params;
		},
		handleStartChat() {
			if (!this.chatInput) {
				this.$message.warning('请输入问题');
			} else if (!this.isEnded) {
				this.$message.warning('请等待前一个问题回答完毕在提出新的问题');
			} else {
				this.chatMessageRequestion();
			}
		},
		chatMessageRequestion() {
			let thought = '';
			let thoughtTime = 0;
			let thoughtTimer = null;
			let params = this.formatSubmitParams();
			this.sseInstance = new SSE('/v1/chat-messages', {
				method: 'POST',
				payload: JSON.stringify(params),
				headers: {
					'Content-Type': 'application/json;charset=UTF-8',
					Authorization: 'Bearer app-poPLtKUWKzDduMB6mXHOYqad'
				}
			});
			this.isEnded = false;
			this.contents.push({
				question: lodash.pick(params, ['query', 'user']),
				answer: {}
			});
			this.$refs['chatRef'].clear();
			this.sseInstance.onmessage = (event) => {
				let datas = JSON.parse(event.data);
				let lastData = lodash.last(this.contents);
				if (datas.event === 'workflow_started') {
					this.$set(lastData.answer, 'process', []);
				} else if (datas.event === 'node_started') {
					let nodeData = lodash.pick(datas.data, ['id', 'title', 'node_type']);
					lastData.answer.process.push({ ...nodeData, time: 0 });
				} else if (datas.event === 'node_finished') {
					let time = datas.data?.elapsed_time || 0;
					let node = lodash.find(lastData.answer.process, { id: datas.data.id });
					node && (node.time = time > 1 ? `${time.toFixed(3)}s` : `${(time * 1000).toFixed(3)}ms`);
				} else if (datas.event === 'message_end') {
					this.$set(lastData.answer, 'isFinish', true);
					this.workflowFinish();
				} else if (datas.event === 'error') {
					this.$set(lastData.answer, 'error', datas.message);
					this.$set(lastData.answer, 'isError', true);
					this.workflowFinish();
				} else if (datas.event === 'message') {
					if (datas.answer === '<think>') {
						if (!thoughtTimer) {
							thoughtTimer = setInterval(() => {
								thoughtTime += 1;
								this.$set(lastData.answer, 'thoughtTime', thoughtTime);
							}, 10);
						} else {
							clearInterval(thoughtTimer);
						}
						thought = `<div class="ideabox"><p>`;
					} else if (datas.answer === '</think>') {
						thought += `</div>`;
						clearInterval(thoughtTimer);
					} else {
						thought += datas.answer;
					}
					this.$set(lastData.answer, 'thought', parseMarkdown(thought));
				}
			};
		},
		workflowFinish() {
			this.sseInstance.close();
			this.sseInstance = null;
			this.isEnded = true;
		}
	}
};
</script>
